#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
营业执照识别错误处理模块
定义营业执照识别特有的错误类型和统一错误处理机制
"""

import logging
import traceback
from typing import Dict, Optional, Any
from enum import Enum


class BusinessLicenseErrorType(Enum):
    """营业执照识别错误类型枚举"""
    
    # 文件相关错误
    FILE_NOT_FOUND = "file_not_found"
    FILE_EMPTY = "file_empty"
    FILE_FORMAT_UNSUPPORTED = "file_format_unsupported"
    FILE_SIZE_EXCEEDED = "file_size_exceeded"
    FILE_CORRUPTED = "file_corrupted"
    FILE_READ_ERROR = "file_read_error"
    
    # 网络相关错误
    NETWORK_URL_INVALID = "network_url_invalid"
    NETWORK_CONNECTION_FAILED = "network_connection_failed"
    NETWORK_DOWNLOAD_TIMEOUT = "network_download_timeout"
    NETWORK_REMOTE_FILE_NOT_FOUND = "network_remote_file_not_found"
    NETWORK_PROTOCOL_UNSUPPORTED = "network_protocol_unsupported"
    
    # OCR识别相关错误
    OCR_ENGINE_INIT_FAILED = "ocr_engine_init_failed"
    OCR_RECOGNITION_FAILED = "ocr_recognition_failed"
    OCR_IMAGE_PREPROCESSING_FAILED = "ocr_image_preprocessing_failed"
    OCR_TEXT_EXTRACTION_FAILED = "ocr_text_extraction_failed"
    OCR_NO_TEXT_DETECTED = "ocr_no_text_detected"
    
    # 识别内容相关错误
    RECOGNITION_NO_KEY_FIELDS = "recognition_no_key_fields"
    RECOGNITION_INVALID_LICENSE_FORMAT = "recognition_invalid_license_format"
    RECOGNITION_VERSION_DETECTION_FAILED = "recognition_version_detection_failed"
    RECOGNITION_FIELD_EXTRACTION_FAILED = "recognition_field_extraction_failed"
    
    # 数据验证相关错误
    VALIDATION_CREDIT_CODE_INVALID = "validation_credit_code_invalid"
    VALIDATION_REGISTRATION_NUMBER_INVALID = "validation_registration_number_invalid"
    VALIDATION_DATE_FORMAT_INVALID = "validation_date_format_invalid"
    VALIDATION_REQUIRED_FIELDS_MISSING = "validation_required_fields_missing"
    VALIDATION_DATA_INCONSISTENT = "validation_data_inconsistent"
    
    # 系统资源相关错误
    SYSTEM_MEMORY_INSUFFICIENT = "system_memory_insufficient"
    SYSTEM_TEMP_FILE_CREATION_FAILED = "system_temp_file_creation_failed"
    SYSTEM_TEMP_FILE_CLEANUP_FAILED = "system_temp_file_cleanup_failed"
    SYSTEM_RESOURCE_EXHAUSTED = "system_resource_exhausted"
    
    # 通用系统错误
    SYSTEM_INTERNAL_ERROR = "system_internal_error"
    SYSTEM_UNKNOWN_ERROR = "system_unknown_error"


class BusinessLicenseError(Exception):
    """营业执照识别自定义异常基类"""
    
    def __init__(self, 
                 error_type: BusinessLicenseErrorType,
                 message: str,
                 details: Optional[Dict[str, Any]] = None,
                 original_exception: Optional[Exception] = None):
        """
        初始化营业执照错误
        
        Args:
            error_type: 错误类型
            message: 错误消息
            details: 错误详细信息
            original_exception: 原始异常对象
        """
        self.error_type = error_type
        self.message = message
        self.details = details or {}
        self.original_exception = original_exception
        
        super().__init__(self.message)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式，用于API响应"""
        result = {
            'error_type': self.error_type.value,
            'error_message': self.message,
            'details': self.details
        }
        
        if self.original_exception:
            result['original_error'] = str(self.original_exception)
            result['original_error_type'] = type(self.original_exception).__name__
        
        return result


class BusinessLicenseFileError(BusinessLicenseError):
    """文件相关错误"""
    pass


class BusinessLicenseNetworkError(BusinessLicenseError):
    """网络相关错误"""
    pass


class BusinessLicenseOCRError(BusinessLicenseError):
    """OCR识别相关错误"""
    pass


class BusinessLicenseRecognitionError(BusinessLicenseError):
    """识别内容相关错误"""
    pass


class BusinessLicenseValidationError(BusinessLicenseError):
    """数据验证相关错误"""
    pass


class BusinessLicenseSystemError(BusinessLicenseError):
    """系统资源相关错误"""
    pass


class BusinessLicenseErrorHandler:
    """营业执照错误处理器"""
    
    def __init__(self, logger: Optional[logging.Logger] = None):
        """
        初始化错误处理器
        
        Args:
            logger: 日志记录器，如果为None则使用默认logger
        """
        self.logger = logger or logging.getLogger(__name__)
    
    def handle_error(self, 
                    error: Exception,
                    context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        统一错误处理方法
        
        Args:
            error: 异常对象
            context: 错误上下文信息
            
        Returns:
            Dict: 标准化的错误响应
        """
        context = context or {}
        
        # 如果是自定义的营业执照错误，直接处理
        if isinstance(error, BusinessLicenseError):
            return self._handle_business_license_error(error, context)
        
        # 根据异常类型映射到营业执照错误
        mapped_error = self._map_exception_to_business_license_error(error, context)
        return self._handle_business_license_error(mapped_error, context)
    
    def _handle_business_license_error(self, 
                                     error: BusinessLicenseError,
                                     context: Dict[str, Any]) -> Dict[str, Any]:
        """处理营业执照自定义错误"""
        
        # 记录错误日志
        log_data = {
            'error_type': error.error_type.value,
            'error_message': error.message,
            'context': context,
            'details': error.details
        }
        
        if error.original_exception:
            log_data['original_exception'] = str(error.original_exception)
            log_data['traceback'] = traceback.format_exc()
        
        # 根据错误严重程度选择日志级别
        if error.error_type in [
            BusinessLicenseErrorType.SYSTEM_INTERNAL_ERROR,
            BusinessLicenseErrorType.SYSTEM_UNKNOWN_ERROR,
            BusinessLicenseErrorType.OCR_ENGINE_INIT_FAILED,
            BusinessLicenseErrorType.SYSTEM_RESOURCE_EXHAUSTED
        ]:
            self.logger.error(f"营业执照识别严重错误: {log_data}")
        elif error.error_type in [
            BusinessLicenseErrorType.OCR_RECOGNITION_FAILED,
            BusinessLicenseErrorType.RECOGNITION_NO_KEY_FIELDS,
            BusinessLicenseErrorType.NETWORK_CONNECTION_FAILED
        ]:
            self.logger.warning(f"营业执照识别警告: {log_data}")
        else:
            self.logger.info(f"营业执照识别信息: {log_data}")
        
        # 生成用户友好的错误消息
        user_message = self._get_user_friendly_message(error.error_type, error.message)
        
        # 构建标准化响应
        response = {
            'success': False,
            'error': user_message,
            'error_type': error.error_type.value,
            'error_details': error.details
        }
        
        # 在开发环境中包含更多调试信息
        if context.get('debug_mode', False):
            response['debug_info'] = {
                'original_message': error.message,
                'original_exception': str(error.original_exception) if error.original_exception else None,
                'traceback': traceback.format_exc() if error.original_exception else None
            }
        
        return response
    
    def _map_exception_to_business_license_error(self, 
                                               error: Exception,
                                               context: Dict[str, Any]) -> BusinessLicenseError:
        """将通用异常映射为营业执照特定错误"""
        
        error_str = str(error).lower()
        error_type_name = type(error).__name__
        
        # 文件相关错误映射
        if isinstance(error, FileNotFoundError):
            return BusinessLicenseFileError(
                BusinessLicenseErrorType.FILE_NOT_FOUND,
                f"文件未找到: {str(error)}",
                {'file_path': context.get('file_path')},
                error
            )
        
        if isinstance(error, PermissionError):
            return BusinessLicenseFileError(
                BusinessLicenseErrorType.FILE_READ_ERROR,
                f"文件访问权限不足: {str(error)}",
                {'file_path': context.get('file_path')},
                error
            )
        
        # 网络相关错误映射
        if isinstance(error, ConnectionError) or 'connection' in error_str or 'network' in error_str:
            return BusinessLicenseNetworkError(
                BusinessLicenseErrorType.NETWORK_CONNECTION_FAILED,
                f"网络连接失败: {str(error)}",
                {'url': context.get('url')},
                error
            )
        
        if 'timeout' in error_str:
            return BusinessLicenseNetworkError(
                BusinessLicenseErrorType.NETWORK_DOWNLOAD_TIMEOUT,
                f"网络请求超时: {str(error)}",
                {'url': context.get('url')},
                error
            )
        
        # OCR相关错误映射
        if isinstance(error, RuntimeError) and ('ocr' in error_str or 'rapidocr' in error_str or 'paddleocr' in error_str):
            return BusinessLicenseOCRError(
                BusinessLicenseErrorType.OCR_RECOGNITION_FAILED,
                f"OCR识别失败: {str(error)}",
                {'image_path': context.get('image_path')},
                error
            )
        
        # 内存相关错误映射
        if isinstance(error, MemoryError) or 'memory' in error_str:
            return BusinessLicenseSystemError(
                BusinessLicenseErrorType.SYSTEM_MEMORY_INSUFFICIENT,
                f"系统内存不足: {str(error)}",
                {'memory_usage': context.get('memory_usage')},
                error
            )
        
        # 值错误映射
        if isinstance(error, ValueError):
            if '图像' in error_str or 'image' in error_str:
                return BusinessLicenseFileError(
                    BusinessLicenseErrorType.FILE_CORRUPTED,
                    f"图像文件损坏或格式不支持: {str(error)}",
                    {'file_path': context.get('file_path')},
                    error
                )
            else:
                return BusinessLicenseValidationError(
                    BusinessLicenseErrorType.VALIDATION_DATA_INCONSISTENT,
                    f"数据验证失败: {str(error)}",
                    context,
                    error
                )
        
        # 默认映射为系统内部错误
        return BusinessLicenseSystemError(
            BusinessLicenseErrorType.SYSTEM_INTERNAL_ERROR,
            f"系统内部错误: {str(error)}",
            {
                'exception_type': error_type_name,
                'context': context
            },
            error
        )
    
    def _get_user_friendly_message(self, 
                                 error_type: BusinessLicenseErrorType,
                                 original_message: str) -> str:
        """获取用户友好的错误消息"""
        
        user_messages = {
            # 文件相关错误
            BusinessLicenseErrorType.FILE_NOT_FOUND: "文件未找到，请检查文件路径是否正确",
            BusinessLicenseErrorType.FILE_EMPTY: "上传的文件为空，请选择有效的营业执照图片",
            BusinessLicenseErrorType.FILE_FORMAT_UNSUPPORTED: "不支持的文件格式，请上传JPG、PNG、BMP、TIFF或WEBP格式的图片",
            BusinessLicenseErrorType.FILE_SIZE_EXCEEDED: "文件大小超过限制，最大支持16MB的图片文件",
            BusinessLicenseErrorType.FILE_CORRUPTED: "图片文件损坏或格式异常，请重新上传清晰的营业执照图片",
            BusinessLicenseErrorType.FILE_READ_ERROR: "无法读取文件，请检查文件是否完整或重新上传",
            
            # 网络相关错误
            BusinessLicenseErrorType.NETWORK_URL_INVALID: "提供的URL地址无效，请检查URL格式是否正确",
            BusinessLicenseErrorType.NETWORK_CONNECTION_FAILED: "网络连接失败，请检查网络连接或稍后重试",
            BusinessLicenseErrorType.NETWORK_DOWNLOAD_TIMEOUT: "文件下载超时，请检查网络连接或稍后重试",
            BusinessLicenseErrorType.NETWORK_REMOTE_FILE_NOT_FOUND: "远程文件不存在，请检查URL地址是否正确",
            BusinessLicenseErrorType.NETWORK_PROTOCOL_UNSUPPORTED: "不支持的网络协议，仅支持HTTP和HTTPS协议",
            
            # OCR识别相关错误
            BusinessLicenseErrorType.OCR_ENGINE_INIT_FAILED: "OCR识别引擎初始化失败，请联系系统管理员",
            BusinessLicenseErrorType.OCR_RECOGNITION_FAILED: "OCR识别失败，请确保图片清晰且包含完整的营业执照内容",
            BusinessLicenseErrorType.OCR_IMAGE_PREPROCESSING_FAILED: "图像预处理失败，请检查图片质量或重新上传",
            BusinessLicenseErrorType.OCR_TEXT_EXTRACTION_FAILED: "文本提取失败，请确保图片清晰且光线充足",
            BusinessLicenseErrorType.OCR_NO_TEXT_DETECTED: "未检测到文本内容，请确保上传的是营业执照图片",
            
            # 识别内容相关错误
            BusinessLicenseErrorType.RECOGNITION_NO_KEY_FIELDS: "未识别到营业执照关键信息，请确保图片清晰且包含完整的营业执照内容",
            BusinessLicenseErrorType.RECOGNITION_INVALID_LICENSE_FORMAT: "不是有效的营业执照格式，请上传正确的营业执照图片",
            BusinessLicenseErrorType.RECOGNITION_VERSION_DETECTION_FAILED: "无法确定营业执照版本类型，请确保图片完整清晰",
            BusinessLicenseErrorType.RECOGNITION_FIELD_EXTRACTION_FAILED: "字段提取失败，请确保营业执照图片清晰完整",
            
            # 数据验证相关错误
            BusinessLicenseErrorType.VALIDATION_CREDIT_CODE_INVALID: "统一社会信用代码格式不正确，请检查识别结果",
            BusinessLicenseErrorType.VALIDATION_REGISTRATION_NUMBER_INVALID: "注册号格式不正确，请检查识别结果",
            BusinessLicenseErrorType.VALIDATION_DATE_FORMAT_INVALID: "日期格式不正确，请检查识别结果",
            BusinessLicenseErrorType.VALIDATION_REQUIRED_FIELDS_MISSING: "缺少必需的关键字段，请确保营业执照图片完整",
            BusinessLicenseErrorType.VALIDATION_DATA_INCONSISTENT: "识别数据不一致，请检查营业执照图片质量",
            
            # 系统资源相关错误
            BusinessLicenseErrorType.SYSTEM_MEMORY_INSUFFICIENT: "系统内存不足，请稍后重试或联系系统管理员",
            BusinessLicenseErrorType.SYSTEM_TEMP_FILE_CREATION_FAILED: "临时文件创建失败，请稍后重试",
            BusinessLicenseErrorType.SYSTEM_TEMP_FILE_CLEANUP_FAILED: "临时文件清理失败，不影响识别结果",
            BusinessLicenseErrorType.SYSTEM_RESOURCE_EXHAUSTED: "系统资源不足，请稍后重试",
            
            # 通用系统错误
            BusinessLicenseErrorType.SYSTEM_INTERNAL_ERROR: "系统内部错误，请联系系统管理员",
            BusinessLicenseErrorType.SYSTEM_UNKNOWN_ERROR: "未知错误，请联系系统管理员"
        }
        
        return user_messages.get(error_type, f"处理过程中发生错误: {original_message}")


# 全局错误处理器实例
business_license_error_handler = BusinessLicenseErrorHandler()